package com.uxsino.simo.indicator.expression.mvel;

import org.mvel2.UnresolveablePropertyException;
import org.mvel2.integration.VariableResolver;
import org.mvel2.integration.impl.BaseVariableResolverFactory;

import com.uxsino.simo.indicator.NEIndicatorDepo;

public class NEDepoVariableFactory extends BaseVariableResolverFactory {

    /**
     * serial version required by Seriable
     */
    private static final long serialVersionUID = 1L;

    private NEIndicatorDepo depo;

    public NEDepoVariableFactory() {

    }

    public void setDepo(NEIndicatorDepo depo) {
        this.depo = depo;
    }

    @Override
    public VariableResolver createVariable(String name, Object value) {
        VariableResolver vr;

        try {
            (vr = getVariableResolver(name)).setValue(value);
            return vr;
        } catch (UnresolveablePropertyException e) {
            addResolver(name, vr = new NEDepoVariableResolver(depo, name)).setValue(value);
            return vr;
        }
    }

    @Override
    public VariableResolver createVariable(String name, Object value, Class<?> type) {
        VariableResolver vr;
        try {
            vr = getVariableResolver(name);
        } catch (UnresolveablePropertyException e) {
            vr = null;
        }

        if (vr != null && vr.getType() != null) {
            throw new RuntimeException("variable already defined within scope: " + vr.getType() + " " + name);
        } else {
            addResolver(name, vr = new NEDepoVariableResolver(depo, name, type)).setValue(value);
            return vr;
        }
    }

    @Override
    public boolean isTarget(String name) {
        return variableResolvers.containsKey(name);
    }

    @Override
    public boolean isResolveable(String name) {

        if (variableResolvers.containsKey(name) || depo.getNamespace().getIndicator(name) != null
                || (nextFactory != null && nextFactory.isResolveable(name))) {
            return true;
        }
        return false;
    }

    protected VariableResolver addResolver(String name, VariableResolver vr) {
        variableResolvers.put(name, vr);
        return vr;
    }

    @Override
    public VariableResolver getVariableResolver(String name) {
        VariableResolver vr = variableResolvers.get(name);
        if (vr != null) {
            return vr;
        } else if (depo.getNamespace().getIndicator(name) != null) {
            variableResolvers.put(name, vr = new NEDepoVariableResolver(depo, name));
            return vr;
        } else if (nextFactory != null) {
            return nextFactory.getVariableResolver(name);
        }

        throw new UnresolveablePropertyException("unable to resolve variable '" + name + "'");

    }
}
